//
//  QWUploadCore.m
//  117goFramework
//
//  Created by Yunhai.Wu on 15/7/30.
//  Copyright (c) 2015年 117go. All rights reserved.
//

#import "QWUploadCore.h"
#import "IQWUploadDataProvider.h"
#import "IQWUploadDataStorage.h"
#import "QWNetworkContext.h"
#import "IQWUploadResult.h"
#import "IQWUploadHandler.h"
#import "IQWUploadResultHandler.h"
#import "QWUploadConfig.h"
#import "NSDictionary+QWExtension.h"

static QWUploadCore *sharedObject;

@interface QWUploadCore ()
@property (nonatomic, strong) NSLock *lock;
@property (nonatomic, strong) NSMutableArray* dataProviders;
@property (nonatomic, strong) NSMutableDictionary *dataProviderWeights;
@property (nonatomic, strong) NSMutableDictionary *dataStorages;
@property (nonatomic, strong) NSMutableDictionary *handlers;
@property (nonatomic, strong) NSMutableDictionary *resultHandlers;
@end

static dispatch_source_t uploadDispatchSource;

@implementation QWUploadCore

DEF_SINGLETON_INIT(QWUploadCore)

-(void) execUpload:(id<IQWUploadDataProvider>) dataProvider {
    NSArray *uploadDatas = [dataProvider getProcessData:1];
    id<IQWUploadData> uploadData = [uploadDatas count] > 0 ? uploadDatas[0] : nil;
    if (uploadData) {
        id<IQWUploadHandler> handler = _handlers[@([uploadData getType])];
        id<IQWUploadResultHandler> resultHandler = _resultHandlers[@([uploadData getType])];
        
        if (handler) {
            id<IQWUploadResult> result = [handler handle:uploadData];
            [resultHandler handle:result];
        }
    }
}


-(void) upload {
    while (YES && [[QWNetworkContext sharedInstance] isConnection]) {
        BOOL existUploadData = NO;
        for (id<IQWUploadDataProvider> dataProvider in _dataProviders) {
            NSInteger waitUploadCount = [dataProvider waitProcessDataCount];
            NSInteger weight = [_dataProviderWeights[NSStringFromClass([dataProvider class])] integerValue];
            if (waitUploadCount > 0) {
                existUploadData = YES;
                if (weight <= 0) {
                    weight = waitUploadCount;
                }
                for (int i=0; i<weight; i++) {
                    [self execUpload:dataProvider];
                }
            }
        }
        if (!existUploadData) {
            break;
        }
    }
}

/**
 *  添加上传数据到上传队列中
 *
 *  @param uploadData 上传数据
 */
-(BOOL) storage:(id<IQWUploadData>) uploadData {
    if (uploadData) {
        id<IQWUploadDataStorage> dataStorage = _dataStorages[@([uploadData getType])];
        if (dataStorage) {
            return [dataStorage storage:uploadData];
        } else {
            NSLog(@"%@ storage 没有找到相应存储器",NSStringFromClass(self.class));
        }
    }
    return NO;
}

/**
 *  开始上传
 */
-(void) startUpload {
    dispatch_source_merge_data(uploadDispatchSource, 1);
}

/**
 *  停止上传
 */
-(void) stopUpload {
    dispatch_source_merge_data(uploadDispatchSource, 0);
}

-(void) singleInit {
    
    //数据提供者初始化
    self.dataProviders = [[NSMutableArray alloc] init];
    self.dataProviderWeights = [[NSMutableDictionary alloc] init];
    
    NSDictionary *dps = [[QWUploadConfig sharedInstance] dataProviders];
    [dps qw_each:^(id key, id value) {
        NSString *clazzName = NSStringFromClass(key);
        [self.dataProviders addObject:[[key alloc] init]];
        [self.dataProviderWeights setObject:value forKey:clazzName];
    }];
    
    //数据储存器初始化
    self.dataStorages = [[NSMutableDictionary alloc] init];
    
    NSDictionary *dss = [[QWUploadConfig sharedInstance] dataStorages];
    [dss qw_each:^(id key, id value) {
        [self.dataStorages setObject:[[value alloc] init] forKey:key];
    }];
    
    //数据上传处理器
    self.handlers = [[NSMutableDictionary alloc] init];
    NSDictionary *hs = [[QWUploadConfig sharedInstance] uploadHandlers];
    [hs qw_each:^(id key, id value) {
        [self.handlers setObject:[[value alloc] init] forKey:key];
    }];
    
    //数据上传结果处理器
    self.resultHandlers = [[NSMutableDictionary alloc] init];
    NSDictionary *rhs = [[QWUploadConfig sharedInstance] resultHandlers];
    [rhs qw_each:^(id key, id value) {
        [self.resultHandlers setObject:[[value alloc] init] forKey:key];
    }];
    
    self.lock = [[NSLock alloc] init];
    uploadDispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_OR, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
    __block QWUploadCore* selfObjectRef = self;
    dispatch_source_set_event_handler(uploadDispatchSource, ^{
        unsigned long data = dispatch_source_get_data(uploadDispatchSource);
        if (data == 1) {
            [_lock lock];
            [selfObjectRef upload];
            [_lock unlock];
        }
    });
    dispatch_resume(uploadDispatchSource);
    //注册网络变更通知
    [[QWNetworkContext sharedInstance] addNotification:self selector:@selector(handleNetworkChangeNotification:)];
}

-(void) handleNetworkChangeNotification:(NSNotification*) notification {
    if ([[QWNetworkContext sharedInstance] currentStatus] != NotReachable) {
        [self startUpload];
    }
}

-(void)dealloc {
    if (dispatch_source_testcancel(uploadDispatchSource) == 0) {//没被挂起
        dispatch_source_cancel(uploadDispatchSource);//取消
    }
}

@end
